package cc.owoo.godpen.thread;

/**
 * 用于定时执行任务的线程
 * Created by nimensei
 * 2018-10-29 上午 09:46
 **/
public abstract class Threads {
    /**
     * 状态
     */
    private boolean isStop = true;// 是否结束
    private boolean isPause;// 是否暂停
    private boolean isLock;// 线程是否在运行

    /**
     * 暂停
     */
    private long pauseConsumeTime;// 暂停所消耗的时间
    private long pauseTime;// 暂停的时间点
    private boolean beenPause;// 是否暂停过

    /**
     * 线程
     */
    private long oldRunTimes;// 上一次的运行时长
    private long startTime;// 线程开始的时间点
    private double delay;// 间隔时长
    private double target;// 理想的运行时长
    private int nowDelay;// 当前间隔时长
    private int skip;// 跳过的数量
    private int nowSkip;// 当已跳过的数量
    private int count;// 执行次数
    private int nowCount;// 当前已执行的次数
    private int overstepDelay;// 溢出时长

    public static void run(Runnable run) {
        new Thread(run).start();
    }

    public Threads() {
    }

    public Threads(double delay) {
        this.delay = delay;
    }

    public Threads(int count, double delay) {
        this.count = count;
        this.delay = delay;
    }

    /**
     * 计时器
     *
     * @param runnable 运行回调函数
     * @param delay    每次执行延迟
     */
    public static Threads setInterval(Runnable runnable, int delay) {
        if (runnable == null)
            return null;
        Threads threads = new Threads(delay) {
            @Override
            public void run() {
                runnable.run();
            }
        };
        threads.start();
        return threads;
    }

    /**
     * 启动线程
     */
    public void start(double delay) {
        setDelay(delay);
        start();
    }

    /**
     * 重新启动
     *
     * @param delay
     */
    public void restart(double delay) {
        setDelay(delay);
        restart();
    }

    /**
     * 重新启动
     */
    public void restart() {
        threadStop();
        start();
    }

    /**
     * 开始线程
     *
     * @param time
     */
    public void start() {
        synchronized (this) {
            if (isStop) {
                isStop = false;
                startTime = System.currentTimeMillis();
                onStart();
            }
            if (isPause) {
                isPause = false;
                pauseConsumeTime += System.currentTimeMillis() - pauseTime;
                pauseTime = 0;
            }
            if (isLock)
                return;
            isLock = true;
        }
        new Thread() {
            public void run() {
                newThread();
            }
        }.start();
    }

    /**
     * 新线程
     */
    private void newThread() {
        while (!isStop && !isPause) {
            if (beenPause)
                beenPause = false;
            else {
                if (!startRun() && isStop && !isPause)
                    break;
            }
            startDelay();
        }
        target = 0;
        isLock = false;
    }

    /**
     * 开始运行
     */
    private boolean startRun() {
        synchronized (this) {
            target += delay;
        }
        boolean bol;
        synchronized (this) {
            if (bol = nowSkip < skip)
                ++nowSkip;
        }
        if (!bol) {
            synchronized (this) {
                ++nowCount;
            }
            run();
            synchronized (this) {
                if (count != 0) {
                    if (nowCount >= count) {
                        Threads.this.stop();
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     * 进行延迟
     */
    private void startDelay() {
        synchronized (this) {
            nowDelay = (int) (target - (int) getRunedTimes() - 1);
            if (nowDelay < 0) {
                target -= nowDelay;
                overstepDelay = -nowDelay;
            } else
                overstepDelay = 0;
        }
        delay(nowDelay);
    }

    /**
     * 每一次执行的间隔时长
     */
    public void setDelay(double delay) {
        synchronized (this) {
            this.delay = delay;
        }
    }

    /**
     * 获取延迟
     */
    public double getDelay() {
        return delay;
    }

    /**
     * 获取溢出时长
     */
    public int getOverstepDelay() {
        return overstepDelay;
    }

    /**
     * 延迟
     */
    public static void delay(int time) {
        try {
            Thread.sleep(time);
        } catch (Exception e) {
        }
    }

    /**
     * 是否是最后一次运行
     */
    public boolean isEnding() {
        synchronized (this) {
            return nowCount == count;
        }
    }

    /**
     * 获取当前线程运行的总时间，即抛弃掉暂停所花的时间
     */
    public long getRunedTimes() {
        synchronized (this) {
            if (startTime == 0)
                return 0;
            if (isPause)
                return pauseTime - startTime - pauseConsumeTime;
            return System.currentTimeMillis() - startTime - pauseConsumeTime;
        }
    }

    /**
     * 获取上次的运行时长
     */
    public long getOldRunTimes() {
        return oldRunTimes;
    }

    /**
     * 开始时间重置为当前
     */
    public void startTimeToNow() {
        synchronized (this) {
            startTime = System.currentTimeMillis();
        }
    }

    /**
     * 暂停
     */
    public void pause() {
        synchronized (this) {
            if (isPause || isStop)
                return;
            pauseTime = System.currentTimeMillis();
            isPause = true;
            beenPause = true;
        }
    }

    /**
     * 结束
     */
    public void stop() {
        if (threadStop())
            onStop();
    }

    /**
     * 异常停止（不产生停止事件）
     */
    public void forceStop() {
        threadStop();
    }

    private boolean threadStop() {
        synchronized (this) {
            if (isStop)
                return false;
            oldRunTimes = getRunedTimes();
            startTime = 0;
            pauseTime = 0;
            target = 0;
            pauseConsumeTime = 0;
            isPause = false;
            beenPause = false;

            nowSkip = 0;
            nowCount = 0;

            isStop = true;
            return true;
        }
    }

    public boolean isPause() {
        return isPause;
    }

    public boolean isStop() {
        return isStop;
    }

    public boolean isLock() {
        return isLock;
    }

    public int getSkip() {
        return skip;
    }

    public void setSkip(int skip) {
        this.skip = skip;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public int getNowCount() {
        return nowCount;
    }

    /**
     * 开始时
     */
    public void onStart() {
    }

    /**
     * 暂停时
     */
    public void onPause() {
    }

    /**
     * 结束时
     */
    public void onStop() {
    }

    /**
     * 执行类
     */
    public abstract void run();
}
